﻿using System;
using System.Data.SQLite;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
using System.Data;
using System.Configuration;
using LogUtil;
using System.Threading;
using System.Collections.Generic;
using System.Linq;

namespace FID_LearningDataCollection
{
    public partial class BaseForm : Form
    {
        #region 变量
        private String dbAppFilePath = null;
        private byte[] writeMessage = new byte[8];
        private byte[] responseMessage = new byte[255];
        private SQLiteConnection sqLiteConnection;
        // 等待标志位
        private bool waitingFlag;
        private DateTime lastSendTime = DateTime.MinValue;
        private float lastP1 = 0;
        private float lastP2 = 0;
        private DateTime bLastSendTime = DateTime.MinValue;

        private bool FID_ENABLE = false;
        private string fidDayType;
        private int fidChangeHour = 8;
        private string lastKey;
        private int nextFreq = 0;
        private int lastFreq = 0;
        private int currentFreq = 0;
        // 开始时刻，用来构造图中x的值
        DateTime startTime;
        // 调试打印次数
        private int printerCount = 0;
        private Log serverLog;

        private bool isSendSeprately = false;
        private bool isDebug = false;


        private string comName = "";
        private string algorithmType = "";
        private string SimpleFreq = "";

        private System.Timers.Timer refreshTimer;

        private bool refresh_manual = false;

        #endregion

        public BaseForm()
        {
            InitializeComponent();
            chk_PID.CheckedChanged += new EventHandler(chk_PID_CheckedChanged);
            chk_FID.CheckedChanged += new EventHandler(chk_FID_CheckedChanged);

            bool isContinue = InitializeDatabase();
            if (!isContinue)
                System.Environment.Exit(0);
            LoadData(true);
            SetupRefreshTimer();
            Control.CheckForIllegalCrossThreadCalls = false;
            initUI();
            this.serverLog = new Log(LogType.Daily);
            this.serialPort.DataReceived += ReadData;
        }

        private bool InitializeDatabase()
        {
            string dbFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "IcePeak.db");
            if (!File.Exists(dbFilePath))
            {
                MessageBox.Show(
               $"数据库文件 {dbFilePath} 不存在。请确保数据库文件位于程序目录中。",
               "严重错误",
               MessageBoxButtons.OK,
               MessageBoxIcon.Error);

                return false;
            }
            sqLiteConnection = new SQLiteConnection($"Data Source={dbFilePath};Version=3;");
            sqLiteConnection.Open();
            return true;
        }
        private void LoadData(bool isManual)
        {
            if (!this.chk_auto_refresh.Checked && !isManual)
                return;
            // 临时存储新的数据
            List<DataRow> newData = new List<DataRow>();

            string query = @"
            SELECT Freq, MIN(SCTime) AS FirstTime, COUNT(*) AS ItemCount
            FROM StateHistory
            GROUP BY Freq";

            using (SQLiteCommand cmd = new SQLiteCommand(query, sqLiteConnection))
            using (SQLiteDataReader reader = cmd.ExecuteReader())
            {
                int no = 1;
                while (reader.Read())
                {
                    string freq = reader["Freq"].ToString();
                    string firstTime = DateTime.Parse(reader["FirstTime"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
                    int itemCount = Convert.ToInt32(reader["ItemCount"]);

                    newData.Add(new DataRow { No = no++, FirstTime = firstTime, Freq = freq, ItemCount = itemCount });
                }
            }

            // 比较新数据和当前显示的数据
            if (!IsDataEqual(newData))
            {
                // 如果数据不一致，则更新 DataGridView
                UpdateDataGridView(newData);
            }
        }

        private bool IsDataEqual(List<DataRow> newData)
        {
            if (dataGridView1.Rows.Count != newData.Count)
            {
                return false;
            }

            for (int i = 0; i < newData.Count; i++)
            {
                if (dataGridView1.Rows[i].Cells["Learning_No"].Value.ToString() != newData[i].No.ToString() ||
                    dataGridView1.Rows[i].Cells["Learning_Time"].Value.ToString() != newData[i].FirstTime ||
                    dataGridView1.Rows[i].Cells["Learning_Freq"].Value.ToString() != newData[i].Freq ||
                    dataGridView1.Rows[i].Cells["Learning_ItemCount"].Value.ToString() != newData[i].ItemCount.ToString())
                {
                    return false;
                }
            }

            return true;
        }

        private void UpdateDataGridView(List<DataRow> newData)
        {
            dataGridView1.Rows.Clear();

            foreach (var row in newData)
            {
                dataGridView1.Rows.Add(row.No, row.FirstTime, row.Freq, row.ItemCount);
            }
        }

        private void SetupRefreshTimer()
        {
            refreshTimer = new System.Timers.Timer(5000);
            refreshTimer.Elapsed += (s, e) => LoadData(false);
            refreshTimer.Start();
        }

        private void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == dataGridView1.Columns["Learning_Delete"].Index && e.RowIndex >= 0)
            {
                string freqToDelete = dataGridView1.Rows[e.RowIndex].Cells["Learning_Freq"].Value.ToString();
                DeleteData(freqToDelete);
                LoadData(true);
            }
        }

        private void DeleteData(string freq)
        {
            string deleteQuery = "DELETE FROM StateHistory WHERE Freq = @Freq";
            using (SQLiteCommand cmd = new SQLiteCommand(deleteQuery, sqLiteConnection))
            {
                cmd.Parameters.AddWithValue("@Freq", freq);
                cmd.ExecuteNonQuery();
            }
        }


        #region 界面按钮
        // 开始
        private void tsBtnStart_Click(object sender, EventArgs e)
        {
            // 记录初始时间
            this.startTime = DateTime.Now;
            if (this.initSerialPort() != 0) return; // 端口检查


            // 数据记录频率条件检查
            if (checkedListBox1.CheckedItems.Count == 0)
            {
                MessageBox.Show(
               "请选择采集频率!",
               "警告",
               MessageBoxButtons.OK,
               MessageBoxIcon.Warning);
                return;
            }
            else
            {
                foreach (object item in checkedListBox1.CheckedItems)
                {
                    this.SimpleFreq = item.ToString().Replace("Hz", "");
                }
            }

            if (!chk_PID.Checked && !chk_FID.Checked)
            {
                MessageBox.Show("You must select at least one option: PID or FID.", "Selection Required", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            this.init();
            this.serialPort.Open();
            this.timer1.Start();

        }
        // 停止
        private void tsBtnStop_Click(object sender, EventArgs e)
        {
            this.tsBtnStart.Enabled = true;
            this.tsBtnStop.Enabled = false;
            this.tsBtnRefresh.Enabled = true;

            this.timer1.Stop();
            this.nextFreq = 0;
            this.serialPort.Write(UpdatedWriteMessage(), 0, 8);
            if (this.serialPort.IsOpen) this.serialPort.Close();

            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
                checkedListBox1.SetItemChecked(i, false);
            }
            this.checkedListBox1.SelectedItems.Clear();
            this.SimpleFreq = "";
        }
        // 重置
        private void tsBtnRefresh_Click(object sender, EventArgs e)
        {
            this.timer1.Stop();

            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
                checkedListBox1.SetItemChecked(i, false);
            }
            this.checkedListBox1.SelectedItems.Clear();
            this.SimpleFreq = "";

            if (this.serialPort.IsOpen)
                this.serialPort.Close();
            initUI();// 重新初始化界面
        }
        #endregion

        // 定时器
        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                // 记录最后发送消息时间
                this.lastSendTime = DateTime.Now;

                try
                {
                    this.serialPort.Write(UpdatedWriteMessage(), 0, 8);
                }
                catch { }

                // 标志位设置为False
                this.waitingFlag = true;
            }
            catch (Exception ex)
            {
                serverLog.Write("Error: " + ex.Message + "\n");
                Thread.Sleep(1000 * 3); // 3s后
                this.serialPort.PortName = this.comName;
                try
                { // 打开端口
                    if (this.serialPort.IsOpen == true)
                        this.serialPort.Close();
                    this.serialPort.Open();
                }
                catch { }
            }
        }

        // 读取数据回调
        private void ReadData(object o, SerialDataReceivedEventArgs e)
        {
            try
            {
                if (!this.waitingFlag)
                    return;
                // 读取返回的消息
                for (int i = 0; i < 205; i++)
                {
                    this.serialPort.Read(this.responseMessage, i, 1);
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
            // 使用CRC校验解析消息
            if (CRCCheck.GenerateCRC(this.responseMessage, 5, CRCCheck.CRC_DEFAULT_SEED) == 0xFFFF)
            {
                // 异常消息
                serverLog.Write("Received : " + CommonUtil.Message2Hex(this.responseMessage, 5));
            }
            else if (CRCCheck.GenerateCRC(this.responseMessage, 205, CRCCheck.CRC_DEFAULT_SEED) == 0xFFFF)
            {
                // 读命令响应
                WorkingState workingState = CommonUtil.AnalysisResMessage(this.lastSendTime, this.responseMessage,
                this.bLastSendTime, this.lastP1, this.lastP2);
                // 接收成功
                this.waitingFlag = false;
                this.currentFreq = (int)workingState.Freq;
                workingState.LastSendingFreq = this.lastFreq;


                // 界面表格显示
                setGridViewData(workingState);

                string s = "";
                serverLog.Write("---------");
                serverLog.Write(s);

                // 2. 写数据库
                if (this.SimpleFreq == "任意")
                    writeToSqlite(workingState);
                else
                {
                    // 判断频率是否是指定的
                    if (this.SimpleFreq == workingState.Freq.ToString())
                        writeToSqlite(workingState);
                }

            }
        }

        // 写入数据库
        public void writeToSqlite(WorkingState workingState)
        {
            float dp1 = lastP1 - workingState.P1;
            float dp2 = lastP2 - workingState.P2;
            lastP1 = workingState.P1;
            lastP2 = workingState.P2;
            long dt = (this.lastSendTime - this.bLastSendTime).Milliseconds;
            this.bLastSendTime = this.lastSendTime;
            string SCTime = workingState.FormatSCTime();

            SQLiteCommand cmd = sqLiteConnection.CreateCommand();
            StringBuilder strbCmd = new StringBuilder();
            strbCmd.Append(@"INSERT INTO StateHistory (
	                                            SCTime,
	                                            P1,
	                                            P2,
	                                            Freq,
	                                            ECurrent,
	                                            T1,
	                                            T2,
	                                            TEnvir,
	                                            FIDFreq,
	                                            WriteOutFreq,
	                                            WriteOutTime,
	                                            MainBoardWRStatus,
	                                            Superheat,
	                                            PIDOut,
	                                            LimitFlag,
	                                            ICurrent,
	                                            P1Set,
	                                            P1StopSet,
	                                            MinFreq,
	                                            MaxFreq,
	                                            FreqAtMinDelay,
	                                            ControlType,
	                                            deltaEstPressureDiff,
	                                            lastLastDeltaUnknowPressure,
	                                            lastDeltaUnknowPressure,
	                                            nextDeltaUnknowPressureDiff,
	                                            nextNoCompressorPressure,
	                                            deltaTargetPressure,
	                                            PSOFreq
                                            )
                                            VALUES
	                                            (");
            strbCmd.Append("'" + SCTime + "',");
            strbCmd.Append(workingState.P1 + ",");
            strbCmd.Append(workingState.P2 + ",");
            strbCmd.Append(workingState.Freq + ",");
            strbCmd.Append(workingState.ECurrent + ",");
            strbCmd.Append(workingState.T1 + ",");
            strbCmd.Append(workingState.T2 + ",");
            strbCmd.Append(workingState.TEnvir + ",");
            strbCmd.Append(workingState.FIDFreq + ",");
            strbCmd.Append(workingState.WriteOutFreq + ",");
            strbCmd.Append(workingState.WriteOutTime + ",");
            strbCmd.Append(workingState.MainBoardWRStatus == 0 ? "'读'," : "'写',");
            strbCmd.Append(workingState.Superheat + ",");
            strbCmd.Append(workingState.PIDOut + ",");
            strbCmd.Append(workingState.LimitFlag + ",");
            strbCmd.Append(workingState.ICurrent + ",");
            strbCmd.Append(workingState.P1Set + ",");
            strbCmd.Append(workingState.P1StopSet + ",");
            strbCmd.Append(workingState.MinFreq + ",");
            strbCmd.Append(workingState.MaxFreq + ",");
            strbCmd.Append(workingState.FreqAtMinDelay + ",");
            strbCmd.Append(this.FID_ENABLE ? "'FID'," : "'PID',");
            strbCmd.Append(0 + ",");
            strbCmd.Append(0 + ",");
            strbCmd.Append(0 + ",");
            strbCmd.Append(0 + ",");
            strbCmd.Append(0 + ",");
            strbCmd.Append(0 + ",");
            strbCmd.Append(0 + ");");

            cmd.CommandText = strbCmd.ToString();
            cmd.ExecuteNonQuery();

            this.lastKey = SCTime;
        }

        #region 功能函数
        // 制作写类型的消息
        public byte[] UpdatedWriteMessage_1()
        {
            writeMessage[0] = 7;
            writeMessage[1] = 18;
            writeMessage[2] = 0;
            writeMessage[3] = 0;
            writeMessage[4] = 0;
            writeMessage[5] = 100;
            writeMessage[6] = 0;
            writeMessage[7] = 85;
            writeMessage[8] = 0;
            writeMessage[9] = 4;
            writeMessage[10] = 8;
            int freq = Convert.ToInt16(this.nextFreq);
            writeMessage[11] = (byte)(freq >> 8);
            writeMessage[12] = (byte)(freq & 0xFF);
            writeMessage[13] = 0;
            writeMessage[14] = (byte)(this.FID_ENABLE ? 1 : 0);
            writeMessage[15] = 0;
            writeMessage[16] = (byte)(0); // 风扇控制
            writeMessage[17] = 0;
            writeMessage[18] = (byte)(1); // 管路上阀，除学习时间外为1
            int crc = ~CRCCheck.GenerateCRC(writeMessage, 19, CRCCheck.CRC_DEFAULT_SEED);
            //CRC
            writeMessage[19] = (byte)(crc & 0xFF);
            writeMessage[20] = (byte)(crc >> 8);
            return writeMessage;
        }

        public byte[] UpdatedWriteMessage()
        {
            writeMessage[0] = 7;
            writeMessage[1] = 4;
            writeMessage[2] = 0;
            writeMessage[3] = 0;
            writeMessage[4] = 0;
            writeMessage[5] = 100;
            int crc = ~CRCCheck.GenerateCRC(writeMessage, 6, CRCCheck.CRC_DEFAULT_SEED);
            //CRC
            writeMessage[6] = (byte)(crc & 0xFF);
            writeMessage[7] = (byte)(crc >> 8);
            return writeMessage;
        }

        // 打印次数记录和时间
        private string getTime()
        {
            StringBuilder strb = new StringBuilder();
            strb.Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss_fff", DateTimeFormatInfo.InvariantInfo));
            strb.Append(" (");
            strb.Append(this.printerCount++);
            strb.Append("): ");
            return strb.ToString();
        }
        #endregion


        #region 界面程序
        private void setGridViewData(WorkingState workingState)
        {
            string[] newRow = { workingState.GTime(),
                                    Convert.ToString(workingState.P1),
                                    Convert.ToString(workingState.P2),
                                    Convert.ToString(this.lastFreq),
                                    Convert.ToString(workingState.Freq),
                                    Convert.ToString(workingState.T1),
                                    "-",
                                    Convert.ToString(workingState.ECurrent),
                                    Convert.ToString(workingState.T2),
                                    Convert.ToString(workingState.TEnvir) };
            if (this.dataGridView2.Rows.Count == 0)
            {
                this.dataGridView2.Rows.Add(newRow);
            }
            else
            {
                this.dataGridView2.Rows[0].SetValues(newRow);
            }
        }

        // 初始化界面
        private void initUI()
        {
            // 加载数据库
            this.dbAppFilePath = ConfigurationManager.AppSettings["数据库地址"].ToString();

            // 读取Com口,初始化界面
            this.comsToolStripComboBox.Items.Clear();
            string[] str = SerialPort.GetPortNames();
            if (str != null)
            {
                foreach (string s in str)
                {
                    this.comsToolStripComboBox.Items.Add(s);
                }
                this.comsToolStripComboBox.SelectedIndex = 0;
            }
        }

        /// <summary>
        /// 串口初始化
        /// </summary>
        /// <returns></returns>
        private int initSerialPort()
        {
            if (this.comsToolStripComboBox.SelectedIndex < 0)
            {
                MessageBox.Show("请选择端口！");
                return 1;
            }
            else
            {
                this.serialPort.PortName = this.comsToolStripComboBox.SelectedItem.ToString();
                this.comName = this.comsToolStripComboBox.SelectedItem.ToString();
            }

            {
                switch (this.baudrateToolStripComboBox.SelectedIndex)
                {
                    case 0:
                        this.serialPort.BaudRate = 1200;
                        break;
                    case 1:
                        this.serialPort.BaudRate = 2400;
                        break;
                    case 2:
                        this.serialPort.BaudRate = 4800;
                        break;
                    case 3:
                        this.serialPort.BaudRate = 9600;
                        break;
                    case 4:
                        this.serialPort.BaudRate = 19200;
                        break;
                    case 5:
                        this.serialPort.BaudRate = 38400;
                        break;
                    case 6:
                        this.serialPort.BaudRate = 115200;
                        break;
                    default:
                        this.serialPort.BaudRate = 9600;
                        break;
                }

                this.serialPort.DataBits = 8;
                switch (this.checkToolStripComboBox.SelectedIndex)
                {
                    case 0:
                        this.serialPort.StopBits = StopBits.One;
                        this.serialPort.Parity = Parity.None;
                        break;
                    case 1:
                        this.serialPort.StopBits = StopBits.One;
                        this.serialPort.Parity = Parity.Odd;
                        break;
                    case 2:
                        this.serialPort.StopBits = StopBits.One;
                        this.serialPort.Parity = Parity.Even;
                        break;
                    case 3:
                        this.serialPort.StopBits = StopBits.Two;
                        this.serialPort.Parity = Parity.None;
                        break;
                    default:
                        this.serialPort.StopBits = StopBits.One;
                        this.serialPort.Parity = Parity.None;
                        break;
                }
            }
            return 0;
        }


        // 运行前初始化
        private void init()
        {
            float targetP, maxP, minP, m1P, mMaxP;
            int scTime, ccTime, maxFreq, minFreq, startCheckTime, readyCheckTime, stopCheckTime;
            int highStartFreq, lowStartFreq;

            targetP = float.Parse(ConfigurationManager.AppSettings["目标压力"].ToString());
            mMaxP = float.Parse(ConfigurationManager.AppSettings["必开机压力"].ToString());
            maxP = float.Parse(ConfigurationManager.AppSettings["最高压力"].ToString());
            m1P = float.Parse(ConfigurationManager.AppSettings["次高压力"].ToString());
            minP = float.Parse(ConfigurationManager.AppSettings["最小压力"].ToString());

            scTime = (int)(float.Parse(ConfigurationManager.AppSettings["采样周期"].ToString()) * 1000);
            ccTime = (int)(float.Parse(ConfigurationManager.AppSettings["控制周期"].ToString()) * 1000);

            readyCheckTime = (int)(float.Parse(ConfigurationManager.AppSettings["开机准备时间"].ToString()));
            startCheckTime = (int)(float.Parse(ConfigurationManager.AppSettings["开机稳频时间"].ToString()));
            stopCheckTime = (int)(float.Parse(ConfigurationManager.AppSettings["停机检查时间"].ToString()));

            highStartFreq = (int)(float.Parse(ConfigurationManager.AppSettings["高频开机频率"].ToString()));
            lowStartFreq = (int)(float.Parse(ConfigurationManager.AppSettings["低频开机频率"].ToString()));

            maxFreq = int.Parse(ConfigurationManager.AppSettings["最高工作频率"].ToString());
            minFreq = int.Parse(ConfigurationManager.AppSettings["最低工作频率"].ToString());

            fidChangeHour = int.Parse(ConfigurationManager.AppSettings["整点切换时间"].ToString());
            this.fidDayType = ConfigurationManager.AppSettings["FID运行日"].ToString();

            this.tsBtnStart.Enabled = false;
            this.tsBtnStop.Enabled = true;
            this.tsBtnRefresh.Enabled = true;

            // 设置采样周期
            this.timer1.Interval = scTime;
        }

        // checkbox 互斥
        private void chk_PID_CheckedChanged(object sender, EventArgs e)
        {
            if (chk_PID.Checked)
            {
                chk_FID.Checked = false;
                FID_ENABLE = false;
            }
        }

        private void chk_FID_CheckedChanged(object sender, EventArgs e)
        {
            if (chk_FID.Checked)
            {
                chk_PID.Checked = false;
                FID_ENABLE = true;
            }
        }

        #endregion




        private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
                // 如果当前索引不等于正在更改的索引，并且该项目已经被选中，则取消选中
                if (i != e.Index && checkedListBox1.GetItemChecked(i))
                {
                    checkedListBox1.SetItemChecked(i, false);
                }
            }

            // 获取正在勾选或取消勾选的项目
            string item = checkedListBox1.Items[e.Index].ToString();

            // 创建一个列表来存储当前选中的项目
            var checkedItems = checkedListBox1.CheckedItems.Cast<string>().ToList();

            // 如果正在勾选的项目不在已选项目列表中，添加它
            if (e.NewValue == CheckState.Checked && !checkedItems.Contains(item))
            {
                checkedItems.Add(item);
            }
            // 如果正在取消勾选的项目在已选项目列表中，移除它
            else if (e.NewValue == CheckState.Unchecked && checkedItems.Contains(item))
            {
                checkedItems.Remove(item);
            }

            // 检查是否包含 "69Hz" 或 "82Hz"
            if (checkedItems.Contains("69Hz") || checkedItems.Contains("82Hz"))
            {
                MessageBox.Show(
               "请将压缩机步进调为10Hz/s",
               "警告",
               MessageBoxButtons.OK,
               MessageBoxIcon.Warning);
            }
        }

        private void RefreshButton_Click(object sender, EventArgs e)
        {
            LoadData(true);
        }

        private void ClearButton_Click(object sender, EventArgs e)
        {
            var confirmResult = MessageBox.Show(
                "确定要清空所有数据吗？",
                "确认清空",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Warning);

            if (confirmResult == DialogResult.Yes)
            {
                ClearData();
                dataGridView1.Rows.Clear();
            }
        }

        private void ClearData()
        {
            string deleteQuery = "DELETE FROM StateHistory";
            using (SQLiteCommand cmd = new SQLiteCommand(deleteQuery, sqLiteConnection))
            {
                cmd.ExecuteNonQuery();
            }
        }

        private void ExportButton_Click(object sender, EventArgs e)
        {
            // 获取可执行文件所在的目录
            string exeDirectory = AppDomain.CurrentDomain.BaseDirectory;

            try
            {
                List<List<double>> compressData = new Vankdata().GetCompressorData(this.sqLiteConnection);

                // 导出数据到文件
                string exportFilePath = Path.Combine(exeDirectory, "learning_data.txt");
                using (StreamWriter writer = new StreamWriter(exportFilePath, false))
                {
                    foreach (var datas in compressData)
                    {
                        writer.WriteLine(string.Join(" ", datas));
                    }
                }

                MessageBox.Show(
                    "数据成功导出到 learning_data.txt",
                    "导出成功",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);

                string argument = $"/select, \"{exportFilePath}\"";
                System.Diagnostics.Process.Start("explorer.exe", argument);
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    $"导出失败: {ex.Message}",
                    "导出错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void BaseForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (refreshTimer != null)
            {
                refreshTimer.Stop();
                refreshTimer.Dispose();
            }

            if (sqLiteConnection != null)
            {
                sqLiteConnection.Close();
                sqLiteConnection.Dispose();
            }
        }

        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value == null)
            {
                e.Value = "N/A"; // Provide a default value
            }
        }
    }

    // 定义用于存储行数据的类
    public class DataRow
    {
        public int No { get; set; }
        public string FirstTime { get; set; }
        public string Freq { get; set; }
        public int ItemCount { get; set; }
    }
}
